///////////////////////////////////////////////////////////////////////////////
//
// MarkMaths.cpp
// 
// Author:
//      Mark Hobbs mark@hobsie.com
// 
// Copyright (c) 2010 Mark Hobbs
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
///////////////////////////////////////////////////////////////////////////////

#include "MarkMaths.h"

namespace MM
{
	
float dotProduct(const Vector3 *vector1, const Vector3 *vector2)
{
	return (vector1->x * vector2->x)+
		   (vector1->y * vector2->y)+
		   (vector1->z * vector2->z);
}

float dotProduct(const Vector3 &vector1, const Vector3 &vector2)
{
	return (vector1.x * vector2.x)+
		   (vector1.y * vector2.y)+
		   (vector1.z * vector2.z);
}

float dotProduct(const Vector2 *vector1, const Vector2 *vector2)
{
	return (vector1->x*vector2->x)+
		   (vector1->y*vector2->y);
}

float dotProduct(const Vector2 &vector1, const Vector2 &vector2)
{
	return (vector1.x*vector2.x)+
		   (vector1.y*vector2.y);
}

void crossProduct(Vector3 &returnVector, 
				 const Vector3 &vector1, 
				 const Vector3 &vector2)
{
    Vector3 temp;

    // The Cross product of 2 vectors is calculated and returned through returnVector
    temp.x = (vector1.y * vector2.z) - (vector1.z * vector2.y);
    temp.y = (vector1.z * vector2.x) - (vector1.x * vector2.z);
    temp.z = (vector1.x * vector2.y) - (vector1.y * vector2.x);

    returnVector = temp;
}

void quatRotation(Vector3 &returnVector,
                 const Vector3 &vector,
                 const Vector3 &axis,
                 float angle)
{
	MM::Quat R, result;

	R.x = axis.x * sin(angle * 0.5f);
	R.y = axis.y * sin(angle * 0.5f);
	R.z = axis.z * sin(angle * 0.5f);
	R.w = cos(angle * 0.5f);

	MM::Quat conjR = R;

	conjR.conjugate();

	MM::Quat v = MM::Quat(vector);		// v is the point we wish to rotate

	//Result = R * V * R'
	MM::Quat VmultConjR = v * conjR;	// V * R'
	result = R * VmultConjR;			// R multipled by the above
	// Quats are 'associative'

	returnVector = MM::Vector3(result.x, result.y, result.z);
}

} // MM Namespace
